package com.guigusuqi.commonutils.utils;
import com.guigusuqi.commonutils.exeception.BusinessException;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author PDH
 * 华师大中国大学Mooc Java核心技术编程作业，部分代码参考：https://blog.csdn.net/qq_38971856/article/details/94415178
 *
 */
/*验证身份证号码是否正确(带校验算法)
题目内容：
输入一个字符串，请判断是否满足身份证基本要求，并返回具体的生日yyyy-mm-dd。
如果输入数据有误，请输出0000-00-00。
基本要求是：a)必须是18位；b) 前面位数必须是数字，最后一位可以是数字或小写字母；c) 日期是存在的；d)最后一位校验码检查。
校验码规则如下：
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7－9－10－5－8－4－2－1－6－3－7－9－10－5－8－4－2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11，看余数是多少？
4、余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为1－0－X－9－8－7－6－5－4－3－2。
5、通过上面得知如果余数是3，就会在身份证的第18位数字上出现的是9。如果对应的数字是10，身份证的最后一位号码就是罗马数字x。
输入格式:
一个身份证号，18位
输出格式：
yyyy-mm-dd
输入样例：
53010219200508011x
输出样例：
1920-05-08
时间限制：500ms内存限制：32000kb
*/
public class IDCheckUtils
{
    public static boolean checkID(String id)
    {
        //a)必须是18位
        int lc = lengthCheck(id);
        if (lc < 0)  return false;

        //b) 前面位数必须是数字，最后一位可以是数字或小写字母；
        int dic = digitCheck(id);
        if (dic < 0)  return false;

        //c) 日期是存在的。
        int dac = dateCheck(id);
        if (dac < 0) return false;

        //d)最后一位校验码检查。
        int ldc = lastDigitCheck(id);
        if (ldc < 0) return false;

        //所有校验通过后，返回true
        return true;
    }

    public static boolean checkPhone(String phone) {
        String mobileRegEx = "^1[3,4,5,6,7,8,9][0-9]{9}$";//正则表达式

        Pattern pattern = Pattern.compile(mobileRegEx);//函数语法 匹配的正则表达式
        Matcher matcher = pattern.matcher(phone);//进行匹配
        return matcher.matches();
    }

    public static int lengthCheck(String id)
    {
        //a)必须是18位
        if (id.length() != 18)
        {
            System.out.println("输入错误：位数不是18位！");
            return -1;
        }
        return 0;
    }

    public static int digitCheck(String id)
    {
        //b) 前面位数必须是数字，最后一位可以是数字或小写字母；
        int i,n=0;
        for( i=0;i<17;i++)
        {
            if(id.charAt(i)>='0'&&id.charAt(i)<='9')
            {
                n++;
            }
            else
                break;
        }

        if(n<=16||!((id.charAt(17)>='0'&& id.charAt(17)<='9')||(id.charAt(17)>='a'&& id.charAt(17)<='z'))) {
            System.out.println("输入错误：前面位数必须是数字，最后一位可以是数字或小写字母！");
            return -2;
        }
        return 0;
    }

    public static int dateCheck(String id)
    {
        //c) 日期是存在的。
        int year,month,day;
        year=Integer.parseInt(id.substring(6, 10));
        month=Integer.parseInt(id.substring(10, 12));
        day=Integer.parseInt(id.substring(12, 14));

        String strDate = id.substring(6, 14);
        // 准备第一个模板，从字符串中提取出日期数字
        String pat1 = "yyyyMMdd" ;
        // 准备第二个模板，将提取后的日期数字变为指定的格式
        String pat2 = "yyyy-MM-dd" ;
        SimpleDateFormat sdf1 = new SimpleDateFormat(pat1) ;        // 实例化模板对象
        SimpleDateFormat sdf2 = new SimpleDateFormat(pat2) ;        // 实例化模板对象
        Date d = null ;
        try{
            d = sdf1.parse(strDate) ;   // 将给定的字符串中的日期提取出来
        }catch(Exception e){            // 如果提供的字符串格式有错误，则进行异常处理
            e.printStackTrace() ;       // 打印异常信息
        }
        String r=sdf1.format(d);
        if(!r.equals(strDate)) {
            System.out.println("输入错误：无效的出生日期！");
            return -3;
        }
        return 0;
    }

    public static int lastDigitCheck(String id) {
        //d)最后一位校验码检查。
        /*
         * 校验码规则如下：
         * 1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7－9－10－5－8－4－2－1－6－3－7－9－10－5－8－4－2。
         * 2、将这17位数字和系数相乘的结果相加。
         * 3、用加出来和除以11，看余数是多少？
         * 4、余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为1－0－X－9－8－7－6－5－4－3－2。
         * 5、通过上面得知如果余数是3，就会在身份证的第18位数字上出现的是9。如果对应的数字是10，身份证的最后一位号码就是罗马数字x。
         */

        //1.系数数组定义
        int[] factors = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
        //2.求和
        int sum = 0;
        for (int i =0;i<17;i++) {
            sum += (id.charAt(i)-'0')*factors[i];
        }
        //3.取余
        int remainder = sum % 11;
        //4.余数映射数组定义
        char[] mappedDigits = {'1','0','X','9','8','7','6','5','4','3','2'};
        //5.生成最后一位（校验位）
        char lastDigit = mappedDigits[remainder];
//        System.out.println("校验位："+lastDigit);
        //判断输入的最后一位是否符合校验规则
        if (id.charAt(17)!=lastDigit) {
            System.out.println("输入错误：最后一位不符合校验规则");
            return -4;
        }
        return 0;
    }
}


